package model.output;

import model.Request;
import model.Substrate;
import model.components.Link;
import model.components.Node;
import model.components.RequestRouter;
import model.components.RequestSwitch;
import model.components.Server;
import model.components.SubstrateRouter;
import model.components.SubstrateSwitch;
import model.components.VirtualMachine;

public class Results {
	private Substrate substrate;
	
	public Results (Substrate sub) {
		this.substrate=sub;
	}
	
	public double Acceptance_Ratio(double denial, double current_request){
		return (current_request-denial)/current_request;
	}
	
	
	public double Generate_Revenue(Request req){
		double sum=0;
		for (Node x: req.getGraph().getVertices()){
			for (int m=0;m<3;m++){
				if (x instanceof VirtualMachine)
					sum=sum+x.getCpu()+x.getMemory()+((VirtualMachine)x).getDiskSpace();
				else if (x instanceof RequestRouter)
					sum=sum+x.getCpu()+x.getMemory();
				else if (x instanceof RequestSwitch)
					sum=sum+x.getCpu()+x.getMemory();
			}
		}
		
		for (Link current: req.getGraph().getEdges())
			sum=sum+current.getBandwidth();
		
		return sum;
	}
	
	public double avgHops(double[][][] flow){
		double avgHops =0;
		
		for (int k=0; k< flow.length;k++){
			int hop_count=0;
			for (int i=0; i<flow[k].length;i++) {
				for (int j=0; j<flow[k][i].length;j++){
					if (flow[k][i][j]>0){						
						hop_count++;
					}
				}
			}
			avgHops +=hop_count;
		}
		
		return avgHops/flow.length;
	}
	
	
	 public double Cost_Embedding(double[][][] flow, Request req){
		  double cost=0;
		  for (int k=0;k<flow.length;k++){
		   for (int i=0;i<this.substrate.getGraph().getVertexCount();i++){
		    for (int j=0;j<this.substrate.getGraph().getVertexCount();j++){
		     cost=cost+flow[k][i][j];
		    }
		   }
		  }
		  
		  if (cost!=0){
		   for (Node x: req.getGraph().getVertices()){
		    for (int m=0;m<3;m++){
		     if (x instanceof VirtualMachine)
		      cost=cost+x.getCpu()+x.getMemory()+((VirtualMachine)x).getDiskSpace();
		     else if (x instanceof RequestRouter)
		      cost=cost+x.getCpu()+x.getMemory();
		     else if (x instanceof RequestSwitch)
		      cost=cost+x.getCpu()+x.getMemory();
		    }
		   }
		  }
		  
		  return cost;
		 }
	
	public double[] Node_utilization_Server_Cpu(double[] initial){
		double[] n_util=new double[initial.length];
				
		for (Node x: this.substrate.getGraph().getVertices()){
			if (x instanceof Server){
					n_util[x.getId()]=1-(x.getCpu()/initial[x.getId()]);
			}
		}
		return n_util;
	}
	
	public double[] Node_utilization_Server_Memory(double[] initial){
		double[] n_util=new double[initial.length];
				
		for (Node x: this.substrate.getGraph().getVertices()){
			if (x instanceof Server){
					n_util[x.getId()]=1-(x.getMemory()/initial[x.getId()]);
			}
		}
		return n_util;
	}
	
	public double[] Node_utilization_Server_DiskSpace(double[] initial){
		double[] n_util=new double[initial.length];
				
		for (Node x: this.substrate.getGraph().getVertices()){
			if (x instanceof Server){
					n_util[x.getId()]=1-(((Server)x).getDiskSpace()/initial[x.getId()]);
			}
		}
		return n_util;
	}
	
	public double[] Node_utilization_Router_Cpu(double[] initial){
		double[] n_util=new double[initial.length];
				
		for (Node x: this.substrate.getGraph().getVertices()){
			if (x instanceof SubstrateRouter){
					n_util[x.getId()]=1-(x.getCpu()/initial[x.getId()]);
			}
		}
		return n_util;
	}
	
	public double[] Node_utilization_Router_Memory(double[] initial){
		double[] n_util=new double[initial.length];
				
		for (Node x: this.substrate.getGraph().getVertices()){
			if (x instanceof SubstrateRouter){
					n_util[x.getId()]=1-(x.getMemory()/initial[x.getId()]);
			}
		}
		return n_util;
	}
	
	public double[] Node_utilization_Switch_Cpu(double[] initial){
		double[] n_util=new double[initial.length];
				
		for (Node x: this.substrate.getGraph().getVertices()){
			if (x instanceof SubstrateSwitch){
					n_util[x.getId()]=1-(x.getCpu()/initial[x.getId()]);
			}
		}
		return n_util;
	}
	
	public double[] Node_utilization_Switch_Memory(double[] initial){
		double[] n_util=new double[initial.length];
				
		for (Node x: this.substrate.getGraph().getVertices()){
			if (x instanceof SubstrateSwitch){
					n_util[x.getId()]=1-(x.getMemory()/initial[x.getId()]);
			}
		}
		return n_util;
	}
	
	
	public double[] Link_utilization(double[] initial){
		double[] l_util=new double[initial.length];
		
		for (Link current: this.substrate.getGraph().getEdges()){
			l_util[current.getId()]= 1-((double) current.getBandwidth()/initial[current.getId()]);
/*			System.out.println("Link:"+current.getId()+ " uitl: "+current.getBandwidth()/initial[current.getId()]);
			System.out.println("current: "+current.getBandwidth());
			System.out.println("initial: "+initial[current.getId()]);*/
		}
		return l_util;
	}
	
	
	
}
